﻿#pragma once
#include <QObject>
#include "PropertyEditEntry.h"

#define REGISTER_NAME(ClassName) ClassName##PropertyEditEntryRegister

#define REGISTER_PROPERTY_EDIT_ENTRY(ClassName) \
struct REGISTER_NAME(ClassName) { \
    REGISTER_NAME(ClassName)() { \
        ObjectPropertyEditEntryFactory::instance().registerEditEntry([=](const QMetaObject& metaObject, void* object) ->QList<PropertyEditEntry*> { \
            if (metaObject.className() == Q##ClassName::staticMetaObject.className()) { \
                const auto entry = new ClassName##PropertyEditEntry; \
                entry->setObject(object); \
                return { entry }; \
            } \
            return {}; \
        }); \
    } \
}; static REGISTER_NAME(ClassName) singleton_##ClassName##Register;

class ObjectPropertyEditEntryFactory {
    Q_DISABLE_COPY_MOVE(ObjectPropertyEditEntryFactory)
protected:
    ObjectPropertyEditEntryFactory();
public:
    static ObjectPropertyEditEntryFactory &instance() {
        static ObjectPropertyEditEntryFactory singleton;
        return singleton;
    }
    using EdidEntryCreater = std::function<QList<PropertyEditEntry*>(const QMetaObject &mataObject, void *object)>;
    void registerEditEntry(const EdidEntryCreater &functor) {
        mEntryCreators.append(functor);
    }
    QList<PropertyEditEntry*> createEditEntries(const QMetaObject &mataObject, void *object) {
        for(const auto &creator : mEntryCreators) {
            const auto &entryList = creator(mataObject, object);
            if(!entryList.isEmpty()) {
                return entryList;
            }
        }
        return QList<PropertyEditEntry*>();
    }

private:
    QList<EdidEntryCreater> mEntryCreators;
};
